#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <cstring>
#include <cmath>

#include "cJSON.h"


using namespace std;

float resttwo(float num);
void send_data(char *buf);
void StrExtFloat(float *num,char* Str);
void transer(char *buf);

int main(){

    int server_fd, client_fd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_addr_len;
    char buf[1024];

    // create a TCP socket
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0) {
        cerr << "Failed to create socket\n";
        return -1;
    }

    // bind to a specific IP address and port
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("192.168.1.231"); // bind to a specific IP address
    server_addr.sin_port = htons(/*12345*/65300); // use port in USR-TCP232-304 <Serial Port>
//    client_addr.sin_addr.s_addr = inet_addr("192.168.1.230");
//    client_addr.sin_port = htons(/*12345*/65300);
    client_addr.sin_addr.s_addr = inet_addr("192.168.1.202");
    client_addr.sin_port = htons(65300);
    if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        cerr << "Failed to bind to port\n";
        return -1;
    }

    // listen for incoming connections
    if (listen(server_fd, 5) < 0) {
        cerr << "Failed to listen for connections\n";
        return -1;
    }

    cout << "Waiting for connections...\n";

    while (1) {
        // accept a new connection
        client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_addr_len);
        if (client_fd < 0) {
            cerr << "Failed to accept connection\n";
            continue;
        }

        cout << "Accepted connection from " << inet_ntoa(client_addr.sin_addr) << "\n";

        while (1) {
            // read data from the client
            int n = read(client_fd, buf, sizeof(buf)-1);
            if (n < 0) {
                cerr << "Failed to read data from client\n";
                break;
            } else if (n == 0) {
                cout << "Client closed the connection\n";
                break;
            } else {
                buf[n] = '\0';

                cout << "Received data: " << buf << "\n";
                //do something
                transer(buf);
            }
        }

        close(client_fd);
        cout << "Closed connection with " << inet_ntoa(client_addr.sin_addr) << "\n";
    }

    close(server_fd);

    return 0;
}

void send_data(char *buf){
    int server_sockfd = 0;
    int len = 0;
    struct sockaddr_in server_addr;
    int sin_size = 0;
    bzero(&server_addr, sizeof(struct sockaddr_in));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("192.168.1.231");      //("192.168.141.128");
    server_addr.sin_port = htons(9090);

    if((server_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        perror("socket error!\n");
        return ;
    }

    sin_size = sizeof(struct sockaddr_in);

    if((len = sendto(server_sockfd, buf, strlen(buf), 0 ,(struct sockaddr*)&server_addr, sizeof(struct sockaddr))) < 0)
    {
        perror("sendto fail!\n");
        return ;
    }
    close(server_sockfd);

    return;
}

void transer(char *buf){
    //模拟令牌
    cJSON* cjson_token = NULL;
    cjson_token= cJSON_CreateObject();
    cJSON_AddNumberToObject(cjson_token, "coke", 2);
    cJSON_AddStringToObject(cjson_token, "name", "name");
    cJSON_AddStringToObject(cjson_token, "password", "password");
    char* token = cJSON_Print(cjson_token);
    //开始处理
    //第一步,提取气象站发来的数据
    float num[64] = {0.};
    StrExtFloat(num,buf);

    //第二步，封装
    cJSON* cjson_new = NULL;
    cjson_new=cJSON_CreateObject();
    cJSON_AddNumberToObject(cjson_new, "code", 5);
    cJSON_AddItemToObject(cjson_new, "token", cjson_token);
//    std::cout<<"token:"<<token<<std::endl;
    cJSON_AddNumberToObject(cjson_new, "station", 1);
    int time_;
    time_t t;
    time_ = time(&t);
    cJSON_AddNumberToObject(cjson_new, "time", time_);
    cJSON_AddNumberToObject(cjson_new, "temperature", resttwo(num[4]));
    cJSON_AddNumberToObject(cjson_new, "humidity", resttwo(num[5]));
    cJSON_AddNumberToObject(cjson_new, "speed", resttwo(num[1]));
    cJSON_AddNumberToObject(cjson_new, "direction", resttwo(num[3]));
    cJSON_AddNumberToObject(cjson_new, "rain", resttwo(num[7]));
    cJSON_AddNumberToObject(cjson_new, "sunlight", resttwo(num[12]));
    cJSON_AddNumberToObject(cjson_new, "pm25", resttwo(num[9]));
    cJSON_AddNumberToObject(cjson_new, "pm10", resttwo(num[11]));
//    char *buf = NULL;
//    std::cout<<"直接用cjson_Print()输出"<<std::endl;
//    std::cout<<cJSON_Print(cjson_new)<<std::endl;
    char *data=NULL;
    data=cJSON_Print(cjson_new);
//    std::cout << "处理后的数据(transer函数里面的输出)" << std::endl;
//    std::cout << data<< std::endl;
    cJSON_Delete(cjson_new);
    send_data(data);
}

void StrExtFloat(float *num,char* Str)
{
    //遍历深度
    int Fflag = 0;
    //数字个数
    int Fnum = 0;
    char num_start = 0,num_point = 0;
    //遍历到字符串尾部
    while ( *Str != '\0' )
    {
        Fflag++;
        //防止查询超过边界
        if(Fflag>1024)
            break;
        //判断是不是数字
        if(*Str >='0' && *Str <= '9')
        {
            //printf("%c",*Str);
            //判断数字存在
            num_start = 1;
            //判断是否存在小数点
            if(num_point >= 1)
            {
                num_point++;
                //当前小数部分的数值
                float fpoint = *Str - '0';
                for(int i = 1;i<num_point;i++)
                {
                    fpoint = fpoint/10.;
                }
                //加入小数部分
                num[Fnum+1] = num[Fnum+1] + fpoint;
            }
            else
            {
                //加入整数部分
                num[Fnum+1] = num[Fnum+1]*10+(*Str - '0');
            }
        }
        else if(*Str == '.') //判断为小数点
        {
            if(num_start==1)//发现存在小数点
            {
                num_point=1;
            }
        }
        else //判断为其他字符
        {
            if (num_start == 1)
            {
                Fnum++;//统计个数加一
            }
            //清空字符统计与小数点统计
            num_start = 0;
            num_point = 0;
        }
        //指针移动
        *(Str++);
    }
    //如果不是以字符结尾
    if (num_start == 1)
    {
        Fnum++;//统计个数加一
    }
    //放入提取到的数字个数
    num[0] = Fnum;
}

float resttwo(float num){
    //整数部分
    int a=num;
    //十分位部分
    int b=(int)(num*10)%10;
    //百分位部分
    int c=(int)(num*100)%100;
    float d=a+b*0.1+c*0.01;
    return d;
}